package org.jeecg.modules.system.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.model.StartWorkModel;
import org.jeecg.modules.system.model.SysLoginModel;
import org.jeecg.modules.system.model.WorkReportDetaModel;
import org.jeecg.modules.system.model.WorkReportModel;
import org.jeecg.modules.system.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * @Author scott
 * @since 2018-12-17
 */
@RestController
@RequestMapping("/app")
@Api(tags = "给应用端的接口")
@Slf4j
public class AppController {
    @Autowired
    private ITransferRecordService transferRecordService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ISysDepartService sysDepartService;
    @Autowired
    private ISysUserReportService sysUserReportService;
    @Autowired
    private ISysUserReportDetailService sysUserReportDetailService;
    @Autowired
    private ISysTenantService sysTenantService;
    @Autowired
    private ISysDictService sysDictService;
    @Autowired
    private SysUserController sysUserController;
    @Resource
    private BaseCommonService baseCommonService;
    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;

    /**
     * 本地：local minio：minio 阿里：alioss
     */
    @Value(value = "${jeecg.uploadType}")
    private String uploadType;

    @ApiOperation("app登录接口")
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Result<JSONObject> appLogin(@RequestBody SysLoginModel sysLoginModel) {
        Result<JSONObject> result = new Result<JSONObject>();
        String username = sysLoginModel.getUsername();
        String password = sysLoginModel.getPassword();
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername, username);
        SysUser sysUser = sysUserService.getOne(queryWrapper);
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }
        String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
        String syspassword = sysUser.getPassword();
        if (!syspassword.equals(userpassword)) {
            result.error500("用户名或密码错误");
            return result;
        }
        //用户登录信息
        userInfo(sysUser, result);
        LoginUser loginUser = new LoginUser();
        BeanUtils.copyProperties(sysUser, loginUser);
        baseCommonService.addLog("用户名: " + username + ",使用客户端登录成功！", CommonConstant.LOG_TYPE_1, null, loginUser);
        result.setCode(CommonConstant.SC_OK_200);
        return result;
    }

    @ApiOperation("app登出接口")
    @RequestMapping(value = "/logout", method = RequestMethod.POST)
    public Result<JSONObject> logout(@RequestBody StartWorkModel model) {
        Result<JSONObject> result = new Result<JSONObject>();

        SysUser sysUser = sysUserService.getById(model.getUserId());

        //用户登录信息
        LoginUser loginUser = new LoginUser();
        BeanUtils.copyProperties(sysUser, loginUser);
        baseCommonService.addLog("用户名: " + sysUser.getRealname() + ",客户端登出成功！", CommonConstant.LOGOUT_TYPE_1, null, loginUser);
        result.setCode(CommonConstant.SC_OK_200);
        end(model);
        return result;
    }


    /**
     * 用户信息
     *
     * @param sysUser
     * @param result
     * @return
     */
    private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
        String username = sysUser.getUsername();
        String syspassword = sysUser.getPassword();
        // 获取用户部门信息
        JSONObject obj = new JSONObject(new LinkedHashMap<>());

        // 生成token
        String token = JwtUtil.sign(username, syspassword);
        // 设置token缓存有效时间
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);
        obj.put("token", token);

        String tenantIds = sysUser.getRelTenantIds();
        if (oConvertUtils.isNotEmpty(tenantIds)) {
            List<Integer> tenantIdList = new ArrayList<>();
            for (String id : tenantIds.split(SymbolConstant.COMMA)) {
                tenantIdList.add(Integer.valueOf(id));
            }
            // 该方法仅查询有效的租户，如果返回0个就说明所有的租户均无效。
            List<SysTenant> tenantList = sysTenantService.queryEffectiveTenant(tenantIdList);
            if (tenantList.size() == 0) {
                result.error500("与该用户关联的租户均已被冻结，无法登录！");
                return result;
            } else {
                obj.put("tenantList", tenantList);
            }
        }
        // update-end--Author:sunjianlei Date:20210802 for：获取用户租户信息

        obj.put("userInfo", sysUser);
        obj.put("companyInfo", sysUserService.getByName(sysUser.getCreateBy()));

        List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
        obj.put("departs", departs);
        if ("admin".equals(sysUser.getUsername())) {
            obj.put("multi_depart", 1);
        } else if (departs == null || departs.size() == 0) {
            obj.put("multi_depart", 0);
        } else if (departs.size() == 1) {
            sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
            obj.put("multi_depart", 1);
        } else {
            //查询当前是否有登录部门
            // update-begin--Author:wangshuai Date:20200805 for：如果用戶为选择部门，数据库为存在上一次登录部门，则取一条存进去
            SysUser sysUserById = sysUserService.getById(sysUser.getId());
            if (oConvertUtils.isEmpty(sysUserById.getOrgCode())) {
                sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
            }
            // update-end--Author:wangshuai Date:20200805 for：如果用戶为选择部门，数据库为存在上一次登录部门，则取一条存进去
            obj.put("multi_depart", 2);
        }
        obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
        result.setResult(obj);
        result.success("登录成功");
        return result;
    }

    /**
     * 文件上传统一方法
     *
     * @param response
     * @return
     */
    @PostMapping(value = "/upload")
    @ApiOperation("文件上传")
    public Result<?> upload(@ApiParam(name = "file", value = "导入文件", required = true) @RequestParam("file") MultipartFile file, HttpServletResponse response) {
        Result<?> result = new Result<>();
        result.setCode(CommonConstant.SC_OK_200);
        String savePath = "";
        String bizPath = "upload";

        // 获取上传文件对象
        if (oConvertUtils.isEmpty(bizPath)) {
            if (CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)) {
                bizPath = "upload";
            } else {
                bizPath = "";
            }
        }
        if (CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)) {
            savePath = this.uploadLocal(file, bizPath);
        } else {
            savePath = CommonUtils.upload(file, bizPath, uploadType);
        }
        if (oConvertUtils.isNotEmpty(savePath)) {
            result.setMessage(savePath);
            result.setSuccess(true);
        } else {
            result.setMessage("上传失败！");
            result.setSuccess(false);
            result.setCode(CommonConstant.SC_INTERNAL_SERVER_ERROR_500);
        }
        return result;
    }

    /**
     * 本地文件上传
     *
     * @param mf      文件
     * @param bizPath 自定义路径
     * @return
     */
    private String uploadLocal(MultipartFile mf, String bizPath) {
        try {
            String ctxPath = uploadpath;
            String fileName = null;
            File file = new File(ctxPath + File.separator + bizPath + File.separator);
            if (!file.exists()) {
                // 创建文件根目录
                file.mkdirs();
            }
            // 获取文件名
            String orgName = mf.getOriginalFilename();
            orgName = CommonUtils.getFileName(orgName);
            if (orgName.indexOf(SymbolConstant.SPOT) != -1) {
                fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
            } else {
                fileName = orgName + "_" + System.currentTimeMillis();
            }
            String savePath = file.getPath() + File.separator + fileName;
            File savefile = new File(savePath);
            FileCopyUtils.copy(mf.getBytes(), savefile);
            String dbpath = null;
            if (oConvertUtils.isNotEmpty(bizPath)) {
                dbpath = bizPath + File.separator + fileName;
            } else {
                dbpath = fileName;
            }
            if (dbpath.contains(SymbolConstant.DOUBLE_BACKSLASH)) {
                dbpath = dbpath.replace(SymbolConstant.DOUBLE_BACKSLASH, SymbolConstant.SINGLE_SLASH);
            }
            return dbpath;
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return "";
    }

    @RequestMapping(value = "/start", method = RequestMethod.POST)
    @ApiOperation("开始工作")
    @AutoLog(value = "开始工作")
    public Result<?> start(@RequestBody StartWorkModel model) {
        redisUtil.set("work:doing:"+model.getUserId(),LocalDate.now().toString(),12*60*60);

        Result<?> result = new Result<>();
        String date = oConvertUtils.getString(redisUtil.get("start:frequency:"+model.getUserId()));
        if(!StringUtils.isEmpty(date) && date.equals(LocalDate.now().toString())){
            SysUser sysUser = sysUserService.getById(model.getUserId());
            sysUser.setWorkFlag(1);
            sysUserService.updateById(sysUser);

            result.success("成功");
            result.setCode(CommonConstant.SC_OK_200);
            return result;
        }

        SysUser sysUser = sysUserService.getById(model.getUserId());
        if (null!=sysUser.getWorkFlag()&&1==sysUser.getWorkFlag()){
            result.error500("存在正在工作的客户端，请检查。");
            return result;
        }
        sysUser.setWorkFlag(1);
        sysUserService.updateById(sysUser);
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }
        SysUser userParent = sysUserService.getByName(sysUser.getCreateBy());
        if (userParent == null || userParent.getRemainingWork() == null || userParent.getRemainingWork() < 24) {
            result.error500("公司不支持工作，请联系公司。");
            return result;
        }
        userParent.setRemainingWork(userParent.getRemainingWork()-24);
        sysUserService.updateById(userParent);


        // sava record
        TransferRecord transferRecord = new TransferRecord();
        transferRecord.setCreateTime(new Date());
        transferRecord.setCreateBy(sysUser.getId());
        transferRecord.setSourceUserName(sysUser.getRealname());
        transferRecord.setSourceUserAccount(sysUser.getUsername());
        transferRecord.setTargetUserId(userParent.getId());
        transferRecord.setTargetUserName(userParent.getRealname());
        transferRecord.setTargetUserAccount(userParent.getUsername());
        transferRecord.setTransferValue(1);
        transferRecord.setTransferType("2");
        transferRecordService.save(transferRecord);

        result.success("成功");
        result.setCode(CommonConstant.SC_OK_200);
        redisUtil.set("start:frequency:"+model.getUserId(),LocalDate.now().toString(),24*60*60);
        return result;
    }

    @RequestMapping(value = "/end", method = RequestMethod.POST)
    @ApiOperation("停止工作")
    @AutoLog(value = "停止工作")
    public Result<?> end(@RequestBody StartWorkModel model) {

        SysUser sysUser = sysUserService.getById(model.getUserId());
        sysUser.setWorkFlag(0);
        sysUserService.updateById(sysUser);

        redisUtil.del("work:doing:" + model.getUserId());
        Result<?> result = new Result<>();
        result.success("已停止工作");
        result.setCode(CommonConstant.SC_OK_200);
        return result;
    }

    @GetMapping(value = "/setting")
    @ApiOperation("采集配置信息获取")
    @AutoLog(value = "采集配置信息获取")
    public Result<Integer> setting(@RequestParam String userId) {
        return sysUserController.settingGet();
    }

    @RequestMapping(value = "/report", method = RequestMethod.POST)
    @ApiOperation("上报数据")
    @AutoLog(value = "上报数据")
    public Result<?> report(@RequestBody WorkReportModel model) {
        Result<?> result = new Result<>();
        SysUser sysUser = sysUserService.getById(model.getUserId());
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }

//        sysUser.setWorkingHours(sysUser.getWorkingHours() == null ? depart.getAcquisitionFrequency() : sysUser.getWorkingHours() + depart.getAcquisitionFrequency());
//        sysUserService.updateById(sysUser);
        SysUserReport userReport = new SysUserReport();
        userReport.setPic(model.getPic());
        userReport.setUserid(model.getUserId());
        userReport.setCreateBy(model.getUserId());
        userReport.setUpdateBy(model.getUserId());
        userReport.setCreateTime(new Date());
        userReport.setUpdateTime(new Date());
        sysUserReportService.save(userReport);

        for (WorkReportDetaModel detailModel : model.getList()) {
            SysUserReportDetail detail = new SysUserReportDetail();
            detail.setReportId(userReport.getId());
            detail.setCreateBy(model.getUserId());
            detail.setUpdateBy(model.getUserId());
            detail.setCreateTime(new Date());
            detail.setUpdateTime(new Date());
            detail.setType(detailModel.getType());
            detail.setOptTime(detailModel.getOptTime());
            sysUserReportDetailService.save(detail);
        }
        Integer strength = sysUserReportDetailService.getStrength(userReport.getId());
        Integer workHour = sysUserReportDetailService.getWorkHour(userReport.getId());
        LambdaUpdateWrapper<SysUserReport> update = new LambdaUpdateWrapper<>();
        update.set(SysUserReport::getWorkHour,workHour.toString())
                .set(SysUserReport::getStrength,strength.toString())
                .eq(SysUserReport::getId,userReport.getId());
        sysUserReportService.update(update);
        result.success("成功");
        result.setCode(CommonConstant.SC_OK_200);
        return result;
    }
}